package database

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"time"

	_ "github.com/mattn/go-sqlite3"
	"network-firewall-go/internal/types"
)

// Manager 数据库管理器
type Manager struct {
	db   *sql.DB
	path string
}

// NewManager 创建新的数据库管理器
func NewManager(dbPath string) (*Manager, error) {
	// 确保数据库目录存在
	dir := filepath.Dir(dbPath)
	if err := ensureDir(dir); err != nil {
		return nil, fmt.Errorf("创建数据库目录失败: %w", err)
	}

	// 打开数据库连接
	db, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		return nil, fmt.Errorf("打开数据库失败: %w", err)
	}

	manager := &Manager{
		db:   db,
		path: dbPath,
	}

	// 初始化数据库表
	if err := manager.initTables(); err != nil {
		db.Close()
		return nil, fmt.Errorf("初始化数据库表失败: %w", err)
	}

	fmt.Printf("✅ 数据库初始化完成: %s\n", dbPath)
	return manager, nil
}

// Close 关闭数据库连接
func (m *Manager) Close() error {
	if m.db != nil {
		return m.db.Close()
	}
	return nil
}

// initTables 初始化数据库表
func (m *Manager) initTables() error {
	// 创建HTTP请求表
	createRequestsTable := `
	CREATE TABLE IF NOT EXISTS http_requests (
		id TEXT PRIMARY KEY,
		method TEXT NOT NULL,
		url TEXT NOT NULL,
		path TEXT,
		query TEXT,
		headers TEXT, -- JSON格式
		cookies TEXT, -- JSON格式
		body TEXT,
		body_size INTEGER,
		host TEXT,
		remote_addr TEXT,
		user_agent TEXT,
		content_type TEXT,
		http_version TEXT,
		tls_version TEXT,
		timestamp INTEGER NOT NULL
	);`

	// 创建HTTP响应表
	createResponsesTable := `
	CREATE TABLE IF NOT EXISTS http_responses (
		id TEXT PRIMARY KEY,
		request_id TEXT NOT NULL,
		status_code INTEGER NOT NULL,
		status_text TEXT,
		headers TEXT, -- JSON格式
		cookies TEXT, -- JSON格式
		body TEXT,
		body_size INTEGER,
		content_type TEXT,
		http_version TEXT,
		tls_version TEXT,
		timestamp INTEGER NOT NULL,
		FOREIGN KEY (request_id) REFERENCES http_requests(id)
	);`

	// 创建HTTP事务表
	createTransactionsTable := `
	CREATE TABLE IF NOT EXISTS http_transactions (
		id TEXT PRIMARY KEY,
		request_id TEXT NOT NULL,
		response_id TEXT,
		duration INTEGER, -- 毫秒
		created_at INTEGER NOT NULL,
		error TEXT,
		FOREIGN KEY (request_id) REFERENCES http_requests(id),
		FOREIGN KEY (response_id) REFERENCES http_responses(id)
	);`

	// 创建规则表
	createRulesTable := `
	CREATE TABLE IF NOT EXISTS rules (
		id TEXT PRIMARY KEY,
		name TEXT NOT NULL,
		enabled BOOLEAN DEFAULT TRUE,
		conditions TEXT NOT NULL, -- 条件表达式
		actions TEXT NOT NULL,    -- JavaScript代码
		priority INTEGER DEFAULT 0,
		created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
		updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
	);`

	// 创建索引
	createIndexes := []string{
		"CREATE INDEX IF NOT EXISTS idx_requests_timestamp ON http_requests(timestamp);",
		"CREATE INDEX IF NOT EXISTS idx_requests_method ON http_requests(method);",
		"CREATE INDEX IF NOT EXISTS idx_requests_host ON http_requests(host);",
		"CREATE INDEX IF NOT EXISTS idx_responses_status_code ON http_responses(status_code);",
		"CREATE INDEX IF NOT EXISTS idx_transactions_created_at ON http_transactions(created_at);",
		"CREATE INDEX IF NOT EXISTS idx_rules_enabled ON rules(enabled);",
		"CREATE INDEX IF NOT EXISTS idx_rules_priority ON rules(priority);",
	}

	// 执行表创建语句
	tables := []string{
		createRequestsTable,
		createResponsesTable,
		createTransactionsTable,
		createRulesTable,
	}

	for _, table := range tables {
		if _, err := m.db.Exec(table); err != nil {
			return fmt.Errorf("创建表失败: %w", err)
		}
	}

	// 创建索引
	for _, index := range createIndexes {
		if _, err := m.db.Exec(index); err != nil {
			return fmt.Errorf("创建索引失败: %w", err)
		}
	}

	return nil
}

// SaveTransaction 保存HTTP事务
func (m *Manager) SaveTransaction(transaction *types.HTTPTransaction) error {
	tx, err := m.db.Begin()
	if err != nil {
		return fmt.Errorf("开始事务失败: %w", err)
	}
	defer tx.Rollback()

	// 保存请求
	if err := m.saveRequest(tx, transaction.Request); err != nil {
		return fmt.Errorf("保存请求失败: %w", err)
	}

	// 保存响应（如果存在）
	if transaction.Response != nil {
		if err := m.saveResponse(tx, transaction.Response); err != nil {
			return fmt.Errorf("保存响应失败: %w", err)
		}
	}

	// 保存事务
	if err := m.saveTransactionRecord(tx, transaction); err != nil {
		return fmt.Errorf("保存事务记录失败: %w", err)
	}

	return tx.Commit()
}

// saveRequest 保存HTTP请求
func (m *Manager) saveRequest(tx *sql.Tx, req *types.HTTPRequest) error {
	headersJSON, _ := json.Marshal(req.Headers)
	cookiesJSON, _ := json.Marshal(req.Cookies)

	query := `
	INSERT OR REPLACE INTO http_requests (
		id, method, url, path, query, headers, cookies, body, body_size,
		host, remote_addr, user_agent, content_type, http_version, tls_version, timestamp
	) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	_, err := tx.Exec(query,
		req.ID, req.Method, req.URL, req.Path, req.Query,
		string(headersJSON), string(cookiesJSON), req.Body, req.BodySize,
		req.Host, req.RemoteAddr, req.UserAgent, req.ContentType,
		req.HTTPVersion, req.TLSVersion, req.Timestamp)

	return err
}

// saveResponse 保存HTTP响应
func (m *Manager) saveResponse(tx *sql.Tx, resp *types.HTTPResponse) error {
	headersJSON, _ := json.Marshal(resp.Headers)
	cookiesJSON, _ := json.Marshal(resp.Cookies)

	query := `
	INSERT OR REPLACE INTO http_responses (
		id, request_id, status_code, status_text, headers, cookies, body, body_size,
		content_type, http_version, tls_version, timestamp
	) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	_, err := tx.Exec(query,
		resp.ID, resp.RequestID, resp.StatusCode, resp.StatusText,
		string(headersJSON), string(cookiesJSON), resp.Body, resp.BodySize,
		resp.ContentType, resp.HTTPVersion, resp.TLSVersion, resp.Timestamp)

	return err
}

// saveTransactionRecord 保存事务记录
func (m *Manager) saveTransactionRecord(tx *sql.Tx, transaction *types.HTTPTransaction) error {
	var responseID *string
	if transaction.Response != nil {
		responseID = &transaction.Response.ID
	}

	query := `
	INSERT OR REPLACE INTO http_transactions (
		id, request_id, response_id, duration, created_at, error
	) VALUES (?, ?, ?, ?, ?, ?)`

	_, err := tx.Exec(query,
		transaction.ID, transaction.Request.ID, responseID,
		transaction.Duration, transaction.CreatedAt, transaction.Error)

	return err
}

// GetTransactions 获取事务列表
func (m *Manager) GetTransactions(limit, offset int) ([]*types.HTTPTransaction, error) {
	query := `
	SELECT 
		t.id, t.duration, t.created_at, t.error,
		r.id, r.method, r.url, r.path, r.query, r.headers, r.cookies, r.body, r.body_size,
		r.host, r.remote_addr, r.user_agent, r.content_type, r.http_version, r.tls_version, r.timestamp,
		resp.id, resp.status_code, resp.status_text, resp.headers, resp.cookies, resp.body, resp.body_size,
		resp.content_type, resp.http_version, resp.tls_version, resp.timestamp
	FROM http_transactions t
	JOIN http_requests r ON t.request_id = r.id
	LEFT JOIN http_responses resp ON t.response_id = resp.id
	ORDER BY t.created_at DESC
	LIMIT ? OFFSET ?`

	rows, err := m.db.Query(query, limit, offset)
	if err != nil {
		return nil, fmt.Errorf("查询事务失败: %w", err)
	}
	defer rows.Close()

	var transactions []*types.HTTPTransaction
	for rows.Next() {
		transaction, err := m.scanTransaction(rows)
		if err != nil {
			return nil, fmt.Errorf("扫描事务失败: %w", err)
		}
		transactions = append(transactions, transaction)
	}

	return transactions, nil
}

// GetTransactionByID 根据ID获取事务
func (m *Manager) GetTransactionByID(id string) (*types.HTTPTransaction, error) {
	query := `
	SELECT 
		t.id, t.duration, t.created_at, t.error,
		r.id, r.method, r.url, r.path, r.query, r.headers, r.cookies, r.body, r.body_size,
		r.host, r.remote_addr, r.user_agent, r.content_type, r.http_version, r.tls_version, r.timestamp,
		resp.id, resp.status_code, resp.status_text, resp.headers, resp.cookies, resp.body, resp.body_size,
		resp.content_type, resp.http_version, resp.tls_version, resp.timestamp
	FROM http_transactions t
	JOIN http_requests r ON t.request_id = r.id
	LEFT JOIN http_responses resp ON t.response_id = resp.id
	WHERE t.id = ?`

	row := m.db.QueryRow(query, id)
	return m.scanTransaction(row)
}

// scanTransaction 扫描事务行
func (m *Manager) scanTransaction(scanner interface {
	Scan(...interface{}) error
}) (*types.HTTPTransaction, error) {
	var transaction types.HTTPTransaction
	var request types.HTTPRequest
	var response types.HTTPResponse
	var reqHeadersJSON, reqCookiesJSON string
	var respHeadersJSON, respCookiesJSON string
	var respID, respStatusText, respContentType, respHTTPVersion, respTLSVersion *string
	var respStatusCode, respBodySize, respTimestamp *int64
	var respBody *string

	err := scanner.Scan(
		&transaction.ID, &transaction.Duration, &transaction.CreatedAt, &transaction.Error,
		&request.ID, &request.Method, &request.URL, &request.Path, &request.Query,
		&reqHeadersJSON, &reqCookiesJSON, &request.Body, &request.BodySize,
		&request.Host, &request.RemoteAddr, &request.UserAgent, &request.ContentType,
		&request.HTTPVersion, &request.TLSVersion, &request.Timestamp,
		&respID, &respStatusCode, &respStatusText, &respHeadersJSON, &respCookiesJSON,
		&respBody, &respBodySize, &respContentType, &respHTTPVersion, &respTLSVersion, &respTimestamp,
	)
	if err != nil {
		return nil, err
	}

	// 解析请求头和Cookie
	json.Unmarshal([]byte(reqHeadersJSON), &request.Headers)
	json.Unmarshal([]byte(reqCookiesJSON), &request.Cookies)

	transaction.Request = &request

	// 解析响应（如果存在）
	if respID != nil {
		response.ID = *respID
		response.RequestID = request.ID
		if respStatusCode != nil {
			response.StatusCode = int(*respStatusCode)
		}
		if respStatusText != nil {
			response.StatusText = *respStatusText
		}
		if respBody != nil {
			response.Body = *respBody
		}
		if respBodySize != nil {
			response.BodySize = *respBodySize
		}
		if respContentType != nil {
			response.ContentType = *respContentType
		}
		if respHTTPVersion != nil {
			response.HTTPVersion = *respHTTPVersion
		}
		if respTLSVersion != nil {
			response.TLSVersion = *respTLSVersion
		}
		if respTimestamp != nil {
			response.Timestamp = *respTimestamp
		}

		// 解析响应头和Cookie
		if respHeadersJSON != "" {
			json.Unmarshal([]byte(respHeadersJSON), &response.Headers)
		}
		if respCookiesJSON != "" {
			json.Unmarshal([]byte(respCookiesJSON), &response.Cookies)
		}

		transaction.Response = &response
	}

	return &transaction, nil
}

// SaveRule 保存规则
func (m *Manager) SaveRule(rule *types.Rule) error {
	query := `
	INSERT OR REPLACE INTO rules (id, name, enabled, conditions, actions, priority, created_at, updated_at)
	VALUES (?, ?, ?, ?, ?, ?, ?, ?)`

	now := time.Now()
	_, err := m.db.Exec(query,
		rule.ID, rule.Name, rule.Enabled, rule.Conditions, rule.Actions,
		rule.Priority, now, now)

	return err
}

// GetRules 获取规则列表
func (m *Manager) GetRules() ([]*types.Rule, error) {
	query := `
	SELECT id, name, enabled, conditions, actions, priority, created_at, updated_at
	FROM rules
	ORDER BY priority DESC, created_at ASC`

	rows, err := m.db.Query(query)
	if err != nil {
		return nil, fmt.Errorf("查询规则失败: %w", err)
	}
	defer rows.Close()

	var rules []*types.Rule
	for rows.Next() {
		var rule types.Rule
		err := rows.Scan(
			&rule.ID, &rule.Name, &rule.Enabled, &rule.Conditions, &rule.Actions,
			&rule.Priority, &rule.CreatedAt, &rule.UpdatedAt)
		if err != nil {
			return nil, fmt.Errorf("扫描规则失败: %w", err)
		}
		rules = append(rules, &rule)
	}

	return rules, nil
}

// GetRuleByID 根据ID获取规则
func (m *Manager) GetRuleByID(id string) (*types.Rule, error) {
	query := `
	SELECT id, name, enabled, conditions, actions, priority, created_at, updated_at
	FROM rules
	WHERE id = ?`

	var rule types.Rule
	err := m.db.QueryRow(query, id).Scan(
		&rule.ID, &rule.Name, &rule.Enabled, &rule.Conditions, &rule.Actions,
		&rule.Priority, &rule.CreatedAt, &rule.UpdatedAt)

	if err != nil {
		return nil, err
	}

	return &rule, nil
}

// DeleteRule 删除规则
func (m *Manager) DeleteRule(id string) error {
	query := "DELETE FROM rules WHERE id = ?"
	_, err := m.db.Exec(query, id)
	return err
}

// GetStats 获取统计信息
func (m *Manager) GetStats() (map[string]interface{}, error) {
	stats := make(map[string]interface{})

	// 总事务数
	var totalTransactions int64
	err := m.db.QueryRow("SELECT COUNT(*) FROM http_transactions").Scan(&totalTransactions)
	if err != nil {
		return nil, err
	}
	stats["total_transactions"] = totalTransactions

	// 总请求数
	var totalRequests int64
	err = m.db.QueryRow("SELECT COUNT(*) FROM http_requests").Scan(&totalRequests)
	if err != nil {
		return nil, err
	}
	stats["total_requests"] = totalRequests

	// 总规则数
	var totalRules int64
	err = m.db.QueryRow("SELECT COUNT(*) FROM rules").Scan(&totalRules)
	if err != nil {
		return nil, err
	}
	stats["total_rules"] = totalRules

	// 今日事务数
	today := time.Now().Truncate(24 * time.Hour).UnixMilli()
	var todayTransactions int64
	err = m.db.QueryRow("SELECT COUNT(*) FROM http_transactions WHERE created_at >= ?", today).Scan(&todayTransactions)
	if err != nil {
		return nil, err
	}
	stats["today_transactions"] = todayTransactions

	return stats, nil
}

// ensureDir 确保目录存在
func ensureDir(dir string) error {
	if dir == "" || dir == "." {
		return nil
	}

	info, err := os.Stat(dir)
	if err == nil && info.IsDir() {
		return nil
	}

	return os.MkdirAll(dir, 0755)
} 